﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Common
{
    public class ErrorSummary
    {
        public event ErrorListChangeHandler ErrorListChanged;
        public delegate void ErrorListChangeHandler(object o, ErrorSummaryChangedEventArgs e);
        protected virtual void OnErrorListChanged(ErrorSummaryChangedEventArgs e)
        {
            if (ErrorListChanged != null)
                ErrorListChanged(this, e);
        }

        public struct ErrorItem
        {
            public Control ControlItem;
            public string Message;

            public override string ToString()
            {
                return Message;
            }
        }

        public List<ErrorItem> ErrorItemList { get; set; }

        public ErrorSummary()
        {
            ErrorItemList = new List<ErrorItem>();
        }

        public void AddOrOverwriteItem(Control ctrl, string msg)
        {
            ErrorItem elItem = new ErrorItem();
            if (ExistsControl(ctrl))
            {
                ErrorItemList.Remove(ErrorItemList.First(i => i.ControlItem.Equals(ctrl)));
            }

            //Si me pasan "ningun mensaje" es que quieren eliminar.
                if (msg != string.Empty)
                    elItem = AddItem(ctrl, msg);

            OnErrorListChanged(new ErrorSummaryChangedEventArgs(elItem));
            //TODO: agregar evento
        }



        public void AddOrAppendMessage(Control ctrl, string msg)
        {
            ErrorItem elItem;
            if (ExistsControl(ctrl))
            {
                elItem = ErrorItemList.First(i => i.Equals(ctrl));
                elItem.Message += "\n" + msg;
            }
            else
            {
                elItem = AddItem(ctrl, msg);
            }
            OnErrorListChanged(new ErrorSummaryChangedEventArgs(elItem));
        }

        private ErrorItem AddItem(Control ctrl, string msg)
        {
            ErrorItem elNuevo;
            elNuevo.ControlItem = ctrl;
            elNuevo.Message = msg;
            ErrorItemList.Add(elNuevo);
            return elNuevo;
        }

        private bool ExistsControl(Control esteControl)
        {
            return ErrorItemList.Any(i => i.ControlItem.Equals(esteControl));
        }

        public bool HayErrores()
        {
            return ErrorItemList.Count > 0;
        }

        public void CleanErrors()
        {
            ErrorItemList = new List<ErrorItem>();
        }
        /// <summary>
        /// Lista los errores en un listado separado por Enters.-
        /// </summary>
        /// <returns>El listado en un solo string. Si no hay errores retorna string.Empty</returns>
        public override string ToString()
        {
            StringBuilder ret = new StringBuilder();
            if (HayErrores())
            {
                if (ErrorItemList.Count == 1)
                {
                    ret.AppendLine("Por favor revise el siguiente item: ");
                    ret.AppendLine(ErrorItemList[0].Message);
                }
                else
                {
                    ret.AppendLine("Por favor revise los siguientes items: ");
                    ErrorItemList.ForEach(i => ret.AppendLine(i.Message));
                }


            }

            return ret.ToString();
        }

        public void RemoveItem(Control MyControl)
        {
            AddOrOverwriteItem(MyControl, string.Empty);
        }
    }
    public class ErrorSummaryChangedEventArgs : EventArgs
    {
        private ErrorSummary.ErrorItem item { get; set; }
        public Control Ctrl { get { return item.ControlItem; } }
        public string Msg { get { return item.Message; } }
        public ErrorSummaryChangedEventArgs(ErrorSummary.ErrorItem item)
        {
            this.item = item;
        }
        public ErrorSummaryChangedEventArgs()
        {
            this.item = item;
        }
    }
}
